User mode memory allocations for data processing systems can begin as kernel memory allocations. The operating system can then assign memory to applications by mapping virtual memory pages into the application's memory space. While an application can directly allocate page-sized blocks of virtual memory using one of several system level memory mapping functions available across various operating systems, finer grained memory allocations can be made for user mode applications via a variant of the malloc library function. Using a malloc function, a pointer to usable memory can be acquired without requiring the application developer to manually manage virtual memory allocations from the Kernel.
Malloc implementations as known in the art can vary from system to system. Classic malloc implementations begin by requesting a set of virtual memory pages from the kernel, and then returning pointers to free areas within the requested pages. In some implementations, the set of pages can be divided into memory blocks of varying sizes, and allocations of differing sizes can be services from specific blocks of memory. For example, allocations that are multiple pages in size can be allocated from a first memory block, while allocations that are less than a certain fraction of a page size can be allocated from a second memory block.
As the size of the allocations decrease, the number of allocations that can be serviced from a single block of memory increases. However, to manage a larger number of blocks requires maintaining a larger amount of metadata for each allocation. To know which areas within the pages are free at any given time, a malloc implementation maintains metadata about the size and location of each allocated block in use and any free space between blocks. As the program requires more memory, the malloc implementation requests more virtual memory pages, increasing the application's memory footprint. Metadata such as allocation chunk size data headers, or lists of previously allocated or free blocks can be used to manage the memory allocations; managing a large amount of metadata can result in extensive memory management overhead.
Extensive metadata overhead can be particularly seen in data processing systems that make extensive use of object oriented programming models. During runtime, the various objects can perform a large number of small memory allocations, de-allocations, and re-allocations during the life of an object. These repetitious allocation and de-allocation of small amounts of memory can ultimately lead to memory efficiency loss and performance degradation due to the metadata requirements and processing overhead of the large number of allocations.